package labox.innovation.status;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Properties;
import java.util.StringTokenizer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import labox.innovation.config.Config;
import labox.innovation.loginserver.GameServerTable;
import labox.innovation.loginserver.LoginServer;
import labox.innovation.loginserver.LoginController;
import labox.innovation.loginserver.GameServerTable.GameServerInfo;
import labox.innovation.loginserver.LoginController.BanInfo;

public class LoginStatusThread extends Thread {

	private static final Logger _log = LoggerFactory.getLogger(LoginStatusThread.class.getName());

	private Socket _cSocket;

	private PrintWriter _print;

	private BufferedReader _read;

	private boolean _redirectLogger;

	private void telnetOutput(int type, String text) {
		if (type == 1)
			System.out.println("TELNET | " + text);
		else if (type == 2)
			System.out.print("TELNET | " + text);
		else if (type == 3)
			System.out.print(text);
		else if (type == 4)
			System.out.println(text);
		else
			System.out.println("TELNET | " + text);
	}

	private boolean isValidIP(Socket client) {
		boolean result = false;
		InetAddress ClientIP = client.getInetAddress();

		// convert IP to String, and compare with list
		String clientStringIP = ClientIP.getHostAddress();

		telnetOutput(1, "Connection from: " + clientStringIP);

		// read and loop thru list of IPs, compare with newIP
		if (Config.DEVELOPER)
			telnetOutput(2, "");

		InputStream telnetIS = null;
		try {
			Properties telnetSettings = new Properties();
			telnetIS = new FileInputStream(new File(Config.TELNET_FILE));
			telnetSettings.load(telnetIS);

			String HostList = telnetSettings.getProperty("ListOfHosts", "127.0.0.1,localhost");

			if (Config.DEVELOPER)
				telnetOutput(3, "Comparing ip to list...");

			// compare
			String ipToCompare = null;
			for (String ip : HostList.split(",")) {
				if (!result) {
					ipToCompare = InetAddress.getByName(ip).getHostAddress();
					if (clientStringIP.equals(ipToCompare))
						result = true;
					if (Config.DEVELOPER)
						telnetOutput(3, clientStringIP + " = " + ipToCompare + "(" + ip + ") = " + result);
				}
			}
		} catch (IOException e) {
			if (Config.DEVELOPER)
				telnetOutput(4, "");
			telnetOutput(1, "Error: " + e);
		} finally {
			try {
				telnetIS.close();
			} catch (Exception e) {
			}
		}

		if (Config.DEVELOPER)
			telnetOutput(4, "Allow IP: " + result);
		return result;
	}

	public LoginStatusThread(Socket client, int uptime, String StatusPW) throws IOException {
		_cSocket = client;

		_print = new PrintWriter(_cSocket.getOutputStream());
		_read = new BufferedReader(new InputStreamReader(_cSocket.getInputStream()));

		if (isValidIP(client)) {
			telnetOutput(1, client.getInetAddress().getHostAddress() + " accepted.");
			_print.println("Welcome To The Innovation Telnet Session.");
			_print.println("Please Insert Your Password!");
			_print.print("Password: ");
			_print.flush();
			String tmpLine = _read.readLine();
			if (tmpLine == null) {
				_print.println("Error.");
				_print.println("Disconnected...");
				_print.flush();
				_cSocket.close();
			} else {
				if (tmpLine.compareTo(StatusPW) != 0) {
					_print.println("Incorrect Password!");
					_print.println("Disconnected...");
					_print.flush();
					_cSocket.close();
				} else {
					_print.println("Password Correct!");
					_print.println("[Innovation Login Server]");
					_print.print("");
					_print.flush();
					start();
				}
			}
		} else {
			telnetOutput(5, "Connection attempt from " + client.getInetAddress().getHostAddress() + " rejected.");
			_cSocket.close();
		}
	}

	@Override
	public void run() {
		String _usrCommand = "";
		try {
			while (_usrCommand.compareTo("quit") != 0 && _usrCommand.compareTo("exit") != 0) {
				_usrCommand = _read.readLine();
				if (_usrCommand == null) {
					_cSocket.close();
					break;
				}
				if (_usrCommand.equals("help")) {
					_print.println("The following is a list of all available commands: ");
					_print.println("help                                - shows this help.");
					_print.println("status                              - displays basic server statistics.");
					_print.println("unblock <ip>                        - removes <ip> from banlist.");
					_print.println("unrelease <ip>                      - removes <ip> from releaselist.");
					_print.println("block <ip> <time>                   - adds <ip> to banlist.");
					_print.println("release <ip> <time>                 - adds <ip> to releaselist.");
					_print.println("accpattern <pattern>                - change <pattern> to account pattern.");
					_print.println("pwdpattern <pattern>                - change <pattern> to password pattern.");
					_print.println("admin_setconfig <command> <value>   - config command to type value.");
					_print.println("shutdown                            - shuts down server.");
					_print.println("restart                             - restarts the server.");
					_print.println("RedirectLogger                      - Telnet will give you some info about server in real time.");
					_print.println("quit                                - closes telnet session.");
					_print.println("");
				} else if (_usrCommand.equals("status")) {
					_print.println("Game Server:");
					_print.println("Registered Server Count: " + GameServerTable.getInstance().getRegisteredGameServers().size());
					for (GameServerInfo info : GameServerTable.getInstance().getRegisteredGameServers().values()) {
						_print.println("GameServer " + info.getExternalHost() + " state:" + info.getStatus() + " CurrentPlayerCount:" + info.getCurrentPlayerCount());
					}
					_print.println();
					_print.println();
					_print.println("Ban List:");
					for (BanInfo info : LoginController.getInstance().getBannedIps().values()) {
						_print.println("ban address:" + info.getAddress() + " Expired:" + info.hasExpired());
					}
					_print.println();
					_print.println();
					_print.println("Release List:");
					for (BanInfo info : LoginController.getInstance().getReleasedIps().values()) {
						_print.println("release address:" + info.getAddress() + " Expired:" + info.hasExpired());
					}
					_print.println();
					_print.println();
					_print.println("Release List Enable:" + Config.RELEASELIST);
				} else if (_usrCommand.startsWith("unblock")) {
					try {
						_usrCommand = _usrCommand.substring(8);
						if (LoginController.getInstance().removeBanForAddress(_usrCommand)) {
							_log.warn("IP " + _usrCommand + " removed from banlist via TELNET by host: " + _cSocket.getInetAddress().getHostAddress(), Config.SERVER_ID);
							_print.println("The IP " + _usrCommand + " has been removed from the hack protection list!");
						} else {
							_print.println("IP not found in hack protection list...");
						}
					} catch (Exception e) {
						_print.println("Please Enter the IP to Unblock!");
					}
				} else if (_usrCommand.startsWith("unrelease")) {
					try {
						_usrCommand = _usrCommand.substring(10);
						if (LoginController.getInstance().removeReleasedForAddress(_usrCommand)) {
							_log.warn("IP " + _usrCommand + " removed from releaselist via TELNET by host: " + _cSocket.getInetAddress().getHostAddress(), Config.SERVER_ID);
							_print.println("The IP " + _usrCommand + " has been removed from the unrelease list!");
						} else {
							_print.println("IP not found in release list...");
						}
					} catch (Exception e) {
						_print.println("Please Enter the IP to Unrelease!");
					}
				} else if (_usrCommand.startsWith("block")) {
					try {
						_usrCommand = _usrCommand.substring(6);
						String[] c = _usrCommand.split(" ");
						if (c.length > 1) {
							LoginController.getInstance().addBanForAddress(c[0], Long.parseLong(c[1]));
							_log.warn("IP " + _usrCommand + " added to banlist via TELNET by host: " + _cSocket.getInetAddress().getHostAddress(), Config.SERVER_ID);
							_print.println("The IP " + _usrCommand + " has been added to the hack protection list!");
						} else {
							_print.println("IP and Time not incurrent in command...");
						}
					} catch (Exception e) {
						_print.println("Please Enter the IP and Time to block!");
					}
				} else if (_usrCommand.startsWith("release")) {
					try {
						_usrCommand = _usrCommand.substring(8);
						String[] c = _usrCommand.split(" ");
						if (c.length > 1) {
							LoginController.getInstance().addReleasedForAddress(c[0], Long.parseLong(c[1]));
							_log.warn("IP " + _usrCommand + " added to release via TELNET by host: " + _cSocket.getInetAddress().getHostAddress(), Config.SERVER_ID);
							_print.println("The IP " + _usrCommand + " has been added to the release list!");
						} else {
							_print.println("IP and Time not incurrent in command...");
						}
					} catch (Exception e) {
						_print.println("Please Enter the IP and Time to release!");
					}
				} else if (_usrCommand.startsWith("accpattern")) {
					try {
						_usrCommand = _usrCommand.substring(11);
						if (LoginController.getInstance().setNamePattern(_usrCommand)) {
							_log.warn("Pattern: " + _usrCommand + " change to Account Pattern via TELNET by host: " + _cSocket.getInetAddress().getHostAddress(), Config.SERVER_ID);
							_print.println("The Pattern " + _usrCommand + " has been changed to Account Pattern!");
						} else {
							_print.println("pattern change failed");
						}
					} catch (Exception e) {
						_print.println("Please Enter the Pattern to change!");
					}
				} else if (_usrCommand.startsWith("pwdpattern")) {
					try {
						_usrCommand = _usrCommand.substring(11);
						if (LoginController.getInstance().setPasswordPattern(_usrCommand)) {
							_log.warn("Pattern: " + _usrCommand + " change to Password Pattern via TELNET by host: " + _cSocket.getInetAddress().getHostAddress(), Config.SERVER_ID);
							_print.println("The Pattern " + _usrCommand + " has been changed to Password Pattern!");
						} else {
							_print.println("pattern change failed");
						}
					} catch (Exception e) {
						_print.println("Please Enter the Pattern to change!");
					}
				} else if (_usrCommand.startsWith("admin_setconfig")) {
					try {
						_usrCommand = _usrCommand.substring(16);
						String[] value = _usrCommand.split(" ");
						if (value != null && value.length == 2 && Config.setParameterValue(value[0], value[1])) {
							_log.warn("Config parameter " + value[0] + " set to " + value[1] + " via TELNET by host: " + _cSocket.getInetAddress().getHostAddress(), Config.SERVER_ID);
							_print.println("Config parameter " + value[0] + " set to " + value[1]);
						} else
							_print.println("Invalid parameter!");
					} catch (Exception e) {
						_print.println("Usage: admin_setconfig <parameter> <value>");
					}
				} else if (_usrCommand.startsWith("shutdown")) {
					LoginServer.getInstance().shutdown(false);
					_print.println("Bye Bye!");
					_print.flush();
					_cSocket.close();
				} else if (_usrCommand.startsWith("restart")) {
					LoginServer.getInstance().shutdown(true);
					_print.println("Bye Bye!");
					_print.flush();
					_cSocket.close();
				} else if (_usrCommand.equals("RedirectLogger")) {
					_redirectLogger = true;
				} else if (_usrCommand.equals("quit")) { /*
															* Do Nothing :p - Just
															* here to save us from
															* the
															* "Command Not Understood"
															* Text
															*/
				} else if (_usrCommand.length() == 0) { /*
														 * Do Nothing Again -
														 * Same reason as the
														 * quit part
														 */
				} else {
					_print.println("Invalid Command");
				}
				_print.print("");
				_print.flush();
			}
			if (!_cSocket.isClosed()) {
				_print.println("Bye Bye!");
				_print.flush();
				_cSocket.close();
			}
			telnetOutput(1, "Connection from " + _cSocket.getInetAddress().getHostAddress() + " was closed by client.");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void printToTelnet(String msg) {
		synchronized (_print) {
			_print.println(msg);
			_print.flush();
		}
	}

	/**
	 * @return Returns the redirectLogger.
	 */
	public boolean isRedirectLogger() {
		return _redirectLogger;
	}
}
